package com.huawang.mdesign.model.service.util;

import org.apache.commons.lang3.StringUtils;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.regex.Matcher;

import static java.util.regex.Pattern.compile;

/**
 * 字符串比较工具类
 */
public class CompareStringUtils {

    private CompareStringUtils() {
        throw new IllegalStateException("Utility class");
    }


    public static int compareStringOne(String string1, String string2) {
        if (string1 == null && string2 == null) {
            return 0;
        }
        if (string1 == null) {
            return -1;
        }
        if (string2 == null) {
            return 1;
        }
        //拆分两个字符串
        List<String> lstString1 = splitString(string1);
        List<String> lstString2 = splitString(string2);
        //依次对比拆分出的每个值
        return getIndex(lstString1, lstString2);
    }

    private static int getIndex(List<String> lstString1, List<String> lstString2) {
        int index = 0;
        while (true) {
            //相等表示两个字符串完全相等
            if (index >= Math.max(lstString1.size(), lstString2.size())) {
                return 0;
            }
            String str1 = "";
            if (index < lstString1.size()) {
                str1 = lstString1.get(index);
            }
            String str2 = "";
            if (index < lstString2.size()) {
                str2 = lstString2.get(index);
            }
            //字符串相等则继续判断下一组数据
            if (StringUtils.equals(str1, str2)) {
                index++;
                continue;
            }
            //是纯数字，比较数字大小
            if (isNum(str1) && isNum(str2)) {
                return Integer.parseInt(str1) < Integer.parseInt(str2) ? -1 : 1;
            }
            return str1.length() < str2.length() ? -1 : 1;
        }
    }

    /**
     * 分割字符串
     *
     * @param str
     * @return java.util.List<java.lang.String>
     * @author baibf
     * @date 2023/07/20 16:34
     */
    private static List<String> splitString(String str) {

        Matcher matcher = compile("([^0-9]+)|(\\d+)").matcher(str);
        List<String> list = new ArrayList<>();
        while (matcher.find()) {
            list.add(matcher.group());
        }
        return list;
    }

    /**
     * 是否是纯数字
     */
    private static boolean isNum(String str) {
        return compile("\\d+").matcher(str).matches();
    }

    public static final Comparator<String> compareStringTwo = new Comparator<String>() {
        class Int {
            private int i;
        }

        public int findDigitEnd(char[] arrChar, Int at) {
            int k = at.i;
            char c = arrChar[k];
            boolean bFirstZero = (c == '0');
            while (k < arrChar.length) {
                c = arrChar[k];
                //first non-digit which is a high chance.
                if (c > '9' || c < '0') {
                    break;
                }
                if (bFirstZero && c == '0') {
                    at.i++;
                }

                k++;
            }
            return k;
        }

        @Override
        public int compare(String o1, String o2) {
            if (o1 == null && o2 == null) {
                return 0;
            }

            if (o1 == null) {
                return -1;
            }

            if (o2 == null) {
                return 1;
            }

            char[] a = o1.toCharArray();
            char[] b = o2.toCharArray();
            Int aNonzeroIndex = new Int();
            Int bNonzeroIndex = new Int();
            int aIndex = 0;
            int bIndex = 0;
            int aComparedUnitTailIndex;
            int bComparedUnitTailIndex;
            while (aIndex < a.length && bIndex < b.length) {
                //aIndex <
                aNonzeroIndex.i = aIndex;
                bNonzeroIndex.i = bIndex;
                aComparedUnitTailIndex = findDigitEnd(a, aNonzeroIndex);
                bComparedUnitTailIndex = findDigitEnd(b, bNonzeroIndex);
                //compare by number
                if (aComparedUnitTailIndex > aIndex && bComparedUnitTailIndex > bIndex) {
                    int aDigitIndex = aNonzeroIndex.i;
                    int bDigitIndex = bNonzeroIndex.i;
                    int aDigit = aComparedUnitTailIndex - aDigitIndex;
                    int bDigit = bComparedUnitTailIndex - bDigitIndex;
                    //compare by digit
                    if (aDigit != bDigit)
                        return aDigit - bDigit;
                    //the number of their digit is same.
                    while (aDigitIndex < aComparedUnitTailIndex) {
                        if (a[aDigitIndex] != b[bDigitIndex])
                            return a[aDigitIndex] - b[bDigitIndex];
                        aDigitIndex++;
                        bDigitIndex++;
                    }
                    //if they are equal compared by number, compare the number of '0' when start with "0"
                    //ps note: paNonZero and pbNonZero can be added the above loop "while", but it is changed meanwhile.
                    //so, the following comparsion is ok.
                    aDigit = aNonzeroIndex.i - aIndex;
                    bDigit = bNonzeroIndex.i - bIndex;
                    if (aDigit != bDigit)
                        return aDigit - bDigit;
                    aIndex = aComparedUnitTailIndex;
                    bIndex = bComparedUnitTailIndex;
                } else {
                    if (a[aIndex] != b[bIndex])
                        return a[aIndex] - b[bIndex];
                    aIndex++;
                    bIndex++;
                }

            }

            return a.length - b.length;
        }

    };
}
